ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
MailScheduler.c
Go to the documentation of this file.
00001 
00017 #include "derivative.h"
00018 #include "PIT.h"
00019 #include "eDMA.h"
00020 #include "MailDelivery.h"
00021 #include "MailScheduler.h"
00022 /* TEMP ERASE AFTER DEBUG */
00023 #include "Compile_options.h"
00024 /*
00025  ******************************************************************************
00026  * Constants
00027  ******************************************************************************
00028  */
00029 /*
00030  ******************************************************************************
00031  * Globals
00032  ******************************************************************************
00033  */
00034 vuint32_t gu32SchedTickCount;
00035 vuint32_t gu32SchedTxDoneCount;
00036 vuint8_t gu8RescheduleSource;
00037 static uint32_t gu32SchedPITCount;
00038 uint8_t gu8ReSchPITCh;
00039 static uint8_t gu8SchedPITCh;
00040 static uint8_t gu8SchedWriting;
00041 /*
00042  ******************************************************************************
00043  * u8fnSchedConfig
00044  ******************************************************************************
00045  */
00046 uint8_t u8fnSchedConfig(uint32_t u32PITCnt, uint8_t u8PITCh, 
00047                         uint32_t u32ReSchCnt, uint8_t u8ReSchPITCh)
00048 {
00049   uint8_t u8Status;
00050   
00051   u8Status = CLEAR;
00052   
00053   /* Start by stopping any PIT count */
00054   vfnPITStart(u8PITCh, CLEAR);
00055   vfnPITStart(u8ReSchPITCh, CLEAR);
00056   
00057   /* Configure PIT for a periodical wake-up with ISRs need to switch mailboxes */
00058   u8Status = u8fnPITConfig(u8PITCh, u32PITCnt, TRUE);
00059   
00060   /* Prepare the Rescheduling channel as well */
00061   u8Status |= u8fnPITConfig(u8ReSchPITCh, u32ReSchCnt, TRUE);
00062   
00063   /* Continue only if successful */
00064   if(CLEAR == u8Status)
00065   {
00066     /* Restart whatever count we had before */
00067     gu32SchedTickCount = CLEAR;
00068     
00069     /* Remember the passed variables in our globals */
00070     gu32SchedPITCount = u32PITCnt;
00071     gu8SchedPITCh = u8PITCh;
00072     gu8ReSchPITCh = u8ReSchPITCh;
00073   }
00074   else
00075   {
00076     /* Nothing */
00077   }
00078   return (u8Status);
00079 }
00080 /*
00081  ******************************************************************************
00082  * u8fnSchedEnable
00083  ******************************************************************************
00084  */
00085 uint8_t u8fnSchedEnable(uint8_t u8Enable)
00086 {
00087   vfnPITStart(gu8SchedPITCh, u8Enable);
00088   
00089   /* We're starting - we need to init our writing permission */
00090   gu8SchedWriting = MAILBOX_WRITING_ALLOWED;
00091   
00092   return (CLEAR);
00093 }
00094 /*
00095  ******************************************************************************
00096  * u8fnSchedDSPIMailTransfer
00097  ******************************************************************************
00098  */
00099 uint8_t u8fnSchedDSPIMailTransfer(uint8_t u8DSPIInstance,
00100                                   uint8_t u8CS,
00101                                   uint8_t u8ContCS,
00102                                   uint8_t u8EndOfQueueFlag,
00103                                   uint16_t* pu16MsgSrc,
00104                                   uint16_t* pu16MsgResponse,
00105                                   uint16_t u16Size)
00106 {
00107   uint8_t u8Status;
00108   
00109   u8Status = MAILBOX_IS_BEING_WRITTEN;
00110   
00111   /* First, verify we can write */
00112   if(MAILBOX_WRITING_ALLOWED == gu8SchedWriting)
00113   {
00114     /* Lock */
00115     gu8SchedWriting = MAILBOX_WRITING_PROHIBITED;
00116     
00117     /* Start by appending the message to the outbox */
00118     u8Status = u8fnMailboxAppendToDSPIOutbox(u8DSPIInstance, u8CS, u8ContCS,
00119                                              u8EndOfQueueFlag, pu16MsgSrc,
00120                                              u16Size);
00121     if(CLEAR == u8Status)
00122     {
00123       /* Continue by preparing the pointer to the right location once we're done */
00124       u8Status = u8fnMailboxAppendToInbox(pu16MsgResponse, u16Size);
00125     }
00126     else
00127     {
00128       /* nothing, it's been taken care of */
00129     }
00130     
00131     /* Unlock */
00132     gu8SchedWriting = MAILBOX_WRITING_ALLOWED;
00133   }
00134   else
00135   {
00136     /* nothing, it's been taken care of */
00137   }
00138   return (u8Status);
00139 }
00140 /*
00141  ******************************************************************************
00142  * u8fnSchedCompositeDSPIMailTransfer
00143  ******************************************************************************
00144  */
00145 uint8_t u8fnSchedCompositeDSPIMailTransfer(const uint8_t u8DSPIInstance1,
00146                                            const uint8_t u8DSPIInstance2,
00147                                            const uint8_t u8CS,
00148                                            uint16_t* pu16MsgSrc1,
00149                                            uint16_t* pu16MsgSrc2,
00150                                            const uint16_t* pu16MsgResponse,
00151                                            uint16_t u16SizeAtOrigin)
00152 {
00153   uint8_t u8Status;
00154   uint16_t u16SizeAtDestination;
00155   uint16_t u16LastBufferAddress;
00156   
00157 #ifdef DEBUGGING_NOW
00158 //    SIU.GPDO[9].B.PDO = 1;
00159 #endif
00160   u8Status = CLEAR;
00161   u16SizeAtDestination = u16SizeAtOrigin * 2u;
00162   
00163   /* First, verify we can write */
00164   if(MAILBOX_WRITING_ALLOWED == gu8SchedWriting)
00165   {
00166     /* Check that our outbox buffer size is capable of handling the message */
00167     if(gu8MailboxActiveOutboxOffset < OUTBOX_ACTIVE_OUTBOX_IS_2)
00168     {
00169       u16LastBufferAddress = (uint16_t)gu8MailboxActiveOutboxOffset
00170           + u16SizeAtDestination;
00171     }
00172     else
00173     {
00174       u16LastBufferAddress = (uint16_t)gu8MailboxActiveOutboxOffset
00175           + u16SizeAtDestination - OUTBOX_ACTIVE_OUTBOX_IS_2;
00176     }
00177     /* Only continue if we can complete the transaction */
00178     if(OUTBOX_MAX_BUFFER_CNT > u16LastBufferAddress)
00179     {
00180       
00181       /* Lock */
00182       gu8SchedWriting = MAILBOX_WRITING_PROHIBITED;
00183       
00184       /* What we want to do is send a complex message based out of two CITER */
00185       /* locations. We will prepare our outbox to do so by combining messages*/
00186       /* Status will always be clear because otherwise we wouln't have */
00187       /* gotten into this if case */
00188       (void)u8fnMailboxAppendToCompositeDSPIOutbox(u8DSPIInstance1,
00189                                                    u8DSPIInstance2, u8CS,
00190                                                    pu16MsgSrc1, pu16MsgSrc2,
00191                                                    u16SizeAtOrigin);
00192       
00193       /* Continue by preparing the pointer to the right location once we're done */
00194       u8Status
00195           = u8fnMailboxAppendToInbox(pu16MsgResponse, u16SizeAtDestination);
00196       
00197       /* Unlock */
00198       gu8SchedWriting = MAILBOX_WRITING_ALLOWED;
00199     }
00200     else
00201     {
00202       u8Status = MAILBOX_CAPACITY_HAS_BEEN_REACHED;
00203     }
00204   }
00205   else
00206   {
00207     u8Status = MAILBOX_IS_BEING_WRITTEN;
00208   }
00209 #ifdef DEBUGGING_NOW
00210 //  SIU.GPDO[9].B.PDO = 0;
00211 #endif
00212   
00213   return (u8Status);
00214 }
00215 /*
00216  ******************************************************************************
00217  * u32fnSchedHasTimeElapsed
00218  ******************************************************************************
00219  */
00220 uint32_t u32fnSchedHasTimeElapsed(uint32_t u32MyTickCount)
00221 {
00222   uint32_t u32TimeDifference;
00223   
00224   /* Compare passed count with existing count */
00225   if(u32MyTickCount <= gu32SchedTickCount)
00226   {
00227     u32TimeDifference = gu32SchedTickCount - u32MyTickCount;
00228   }
00229   else
00230   {
00231     /* We have over-ran the counter. Still, this means */
00232     /* we're not in the same cycle. */
00233     u32TimeDifference = TRUE;
00234   }
00235   return (u32TimeDifference);
00236 }
00237 /*
00238  ******************************************************************************
00239  * u32fnSchedIsTxDone
00240  ******************************************************************************
00241  */
00242 uint32_t u32fnSchedIsTxDone(uint32_t u32MyTxTime)
00243 {
00244   uint32_t u32TimeDifference;
00245   
00246   /* Compare passed count with existing count */
00247   if(u32MyTxTime <= gu32SchedTxDoneCount)
00248   {
00249     u32TimeDifference = gu32SchedTxDoneCount - u32MyTxTime;
00250   }
00251   else
00252   {
00253     /* We have over-ran the counter. Still, this means */
00254     /* we're not in the same cycle. */
00255     u32TimeDifference = TRUE;
00256   }
00257   return (u32TimeDifference);
00258 }
00259 /*
00260  ******************************************************************************
00261  * vfnSchedIsr
00262  ******************************************************************************
00263  */
00264 void vfnSchedIsr(void)
00265 {
00266   /* Count */
00267   gu32SchedTickCount++;
00268   
00269   /* Force a SW isr */
00270   INTC.SSCIR[4].B.SET = TRUE;
00271   
00272   /*Trigger the appropriate DMA only if we have data */
00273   if((CLEAR != gau32DSPIOutbox[gu8MailboxActiveOutboxOffset])
00274       && (MAILBOX_WRITING_ALLOWED == gu8SchedWriting) 
00275       && (EDMA.TCD[gu8InactiveOutboxDMA].DONE == TRUE))
00276   {
00277     /* Switch Inbox and Outbox */
00278     vfnMailboxSwitchActiveMailboxes();
00279     
00280     vfnDMAMUXInit(gu8InactiveOutboxDMA, DMA_SOURCE_DSPI0_TX, CLEAR, TRUE);
00281     
00282     /* Trigger outbox through empty SPI Tx buffer */
00283     vfnMailDeliveryTriggerOutbox(gu8InactiveOutboxDMA, TRUE);
00284     
00285     /* Trigger inbox as well */
00286     EDMA.SERQR.R = gu8InactiveInboxDMA;
00287   }
00288   else
00289   {
00290     /* Don't trigger */
00291   }
00292   
00293   /* Clear flag that brought us here */
00294   PIT_CLEAR_FLAG(gu8SchedPITCh);
00295   
00296   return;
00297 }
00298 /*
00299  ******************************************************************************
00300  * vfnSchedInboxDoneIsr
00301  ******************************************************************************
00302  */
00303 void vfnSchedInboxDoneIsr(void)
00304 {
00305   /* This fn should be called after receiving all data */
00306    
00307   /* Clear BITER; CITER will be copied to it at launch */
00308   /* (just before becoming active)                     */
00309   EDMA.TCD[gu8InactiveOutboxDMA].BITER = CLEAR;
00310   vfnDMAMUXInit(gu8InactiveOutboxDMA, CLEAR, CLEAR, CLEAR);
00311   vfnDMAMUXInit(gu8InactiveInboxDMA, CLEAR, CLEAR, CLEAR);
00312   vfnDMAMUXInit(gu8InboxDMA, DMA_SOURCE_DSPI0_RX, CLEAR, TRUE);
00313   EDMA.CERQR.R = gu8InactiveInboxDMA;
00314 
00315   /* Once the outbox is empty, the DMA doesn't need to be triggered by */
00316   /* an empty SPI. Disable any MUX to any channel.                     */
00317   DMA_CLEAR_ISR_FLAG(gu8InactiveInboxDMA);
00318 //  DMA_CLEAR_ISR_FLAG(gu8InboxDMA);
00319   
00320   /* Force Software ISRs to call any driver routines associated with having */
00321   /* mail delivered                                                         */
00322 //  INTC.SSCIR[SCHED_INBOX_DONE_SW_ISR_1].B.SET = TRUE;
00323   INTC.SSCIR[SCHED_INBOX_DONE_SW_ISR_2].B.SET = TRUE;
00324   INTC.SSCIR[SCHED_INBOX_DONE_SW_ISR_3].B.SET = TRUE;
00325   INTC.SSCIR[SCHED_INBOX_DONE_SW_ISR_4].B.SET = TRUE;
00326 
00327   /* Increment the Isr count */
00328   gu32SchedTxDoneCount = gu32SchedTickCount;
00329 
00330   return;
00331 }
00332 /*
00333  ******************************************************************************
00334  * vfnReschedulerIsr
00335  ******************************************************************************
00336  */
00337 void vfnReschedulerIsr(void)
00338 {
00339   /* Call appropriate channels */
00340   INTC.SSCIR[SCHED_RESCHED_1].B.SET = 
00341     ((gu8RescheduleSource & RESCH_SRC_1) > CLEAR);
00342   INTC.SSCIR[SCHED_RESCHED_2].B.SET = 
00343     ((gu8RescheduleSource & RESCH_SRC_2) > CLEAR);
00344   INTC.SSCIR[SCHED_RESCHED_3].B.SET = 
00345     ((gu8RescheduleSource & RESCH_SRC_3) > CLEAR);
00346   
00347   if(gu8RescheduleSource == CLEAR)
00348   {
00349     /* End its life */
00350     /* Reschedule. Ch. 1 is for this Isr */
00351     vfnPITStart(gu8ReSchPITCh, CLEAR);
00352   }
00353   else
00354   {
00355     /* We will be back soon enough */
00356   }
00357   
00358   /* Clear Rescheduling flag */
00359   PIT_CLEAR_FLAG(gu8ReSchPITCh);
00360   
00361   return;
00362 }
00363 
00364 /*
00365  ******************************************************************************
00366  *
00367  *  End of file.
00368  *
00369  ******************************************************************************
00370  */